-------------Spell It Plus!------------
A 4am crack                  2015-11-03
---------------------------------------

Name: Spell It Plus!
Genre: educational
Year: 1989
Authors:
  Product Leader: Fave Schwartz
  Product Advisor: Cathy Johnson
  Lead Programmer: Kevin Burley
  Graphic Artist: Carol Carpenter
Publisher: Davidson & Associates, Inc.
Media: 3.5-inch floppy (800K)
OS: ProDOS 1.4
Other versions: Asimov archive has an
  uncredited crack
Similar cracks:
  #481 Math Blaster Mystery 1.3 (3.5")
  #457 Math Blaster Mystery 1.3 (5.25")
  #200 Math Blaster Mystery 1.0 (5.25")
  #166 Word Attack Plus French (5.25")
  #165 Alge-Blaster Plus (5.25")

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


Copy ][+ 9.1 ("COPY" > "DISK")
  read error on block $0308; copy loads
  ProDOS then quits to program selector

CFFA 3000 import
  read error on block 776 (= $0308);
  booting the disk image in an emulator
  exhibits the same behavior as the
  backup I made with Copy ][+ disk copy
  (boots ProDOS then quits via a "Quit"
  MLI call)

It's a very ProDOS-y way of saying
"f--- you."

The original disk boots without
complaint, so either this bad block is
part of the protection check, or it's
unrelated and I got incredibly lucky.

Next steps:

  1. Trace the startup program
  2. Find and disable the protection
     check
  3. Declare victory(*)

(*) Take a nap

                   ~

               Chapter 1
       FORTH? In *My* Apple II?
    It's More Likely Than You Think


[S7,D1=my ProDOS hard drive]
[S5,D1=non-working copy]

]PR#7
...
]CAT,S5,D1

/SPELL

 NAME           TYPE  BLOCKS  MODIFIED

 PRODOS          SYS      32  25-OCT-89
 GMENU.DAT       TXT       3  25-OCT-89
 SPELL.SYSTEM    SYS       4  20-DEC-88
 TK.ABS          BIN      28  25-OCT-89
 GS.OBJ          TXT      13  25-OCT-89
 G4.OVL          TXT      13  26-OCT-89
 PRTREC.OVL      TXT       3  25-OCT-89
 QUOTES.DAT      TXT      12  25-OCT-89
 FOREIGN.FONT.4  BIN       7  25-OCT-89
 G2.OVL          TXT      13  25-OCT-89
 SETUP.OVL       TXT       4  25-OCT-89
 CERT.PAK        TXT       8  25-OCT-89
 SETUP.DAT       TXT       1   2-DEC-91
 TOOLS.OBJ       BIN       3  25-OCT-89
 TEXTCERT.OVL    TXT       3  25-OCT-89
 G1.OVL          TXT      13  25-OCT-89
 DATA            DIR       4  25-OCT-89
 G5.OVL          TXT      13  25-OCT-89
 G3.OVL          TXT      13  25-OCT-89
 ED.OVL          TXT      15  25-OCT-89
 DUMP.HIRES.R    BIN       5  25-OCT-89
 INTER.DRIVERS   TXT       5  25-OCT-89
 PRINTER.DRIVERS TXT      12  25-OCT-89
 HELP.DAT        TXT       4  25-OCT-89
 G5.GRF          TXT      17  25-OCT-89
 G5.OBJ          BIN       3  25-OCT-89
 EMENU.DAT       TXT       3  25-OCT-89
 G3.GR           TXT      18  25-OCT-89
 MAIN.PAK        TXT       8  26-OCT-89
 SIPFIELD.OBJ    BIN       4  25-OCT-89
 SMALL.GR        TXT      19  25-OCT-89
 SILVER.PAK      TXT       4  25-OCT-89
 GOLD.PAK        TXT       4  25-OCT-89
 BRONZE.PAK      TXT       4  25-OCT-89
 TWOPLAYER.GR    TXT       9  25-OCT-89
 G4.GR           TXT       5  25-OCT-89
 ENTRY.PAK       TXT       7  25-OCT-89
 PUZZLE.OBJ      BIN       1  25-OCT-89
 FROG.DAT        TXT       1  25-OCT-89
 AFORTH          BIN      58  26-OCT-89
 MFORTH          BIN      65  26-OCT-89
 CONVERT         SYS       4  25-OCT-89
 UTIL            DIR       1  25-OCT-89
*UTILITIES       SYS      21  25-OCT-89
 STARTUP         BAS       1  25-OCT-89
 DESKTOP         $00       3  16-SEP-56

BLOCKS FREE:  612     BLOCKS USED:  988

ProDOS always loads the first .SYSTEM
file at $2000 and jumps to it.

]PREFIX /SPELL
]BLOAD SPELL.SYSTEM,A$2000,TSYS
]CALL -151

*2000L

2000-   20 D2 25    JSR   $25D2
2003-   4C 74 08    JMP   $0874

There's nothing loaded at $0874 yet, so
the subroutine at $25D2 must load
something from disk or copy something
from memory.

*25D2L

; straightforward memory relocation
25D2-   A2 00       LDX   #$00
25D4-   BD 03 20    LDA   $2003,X
25D7-   9D 01 08    STA   $0801,X
25DA-   BD 03 21    LDA   $2103,X
25DD-   9D 01 09    STA   $0901,X
25E0-   BD 03 22    LDA   $2203,X
25E3-   9D 01 0A    STA   $0A01,X
25E6-   BD 03 23    LDA   $2303,X
25E9-   9D 01 0B    STA   $0B01,X
25EC-   BD 03 24    LDA   $2403,X
25EF-   9D 01 0C    STA   $0C01,X
25F2-   BD 03 25    LDA   $2503,X
25F5-   E8          INX
25F6-   D0 DC       BNE   $25D4
25F8-   60          RTS

That's harmless enough. Let's run it.

*25D2G

*874L

0874-   20 C8 0A    JSR   $0AC8
0877-   F0 D9       BEQ   $0852

*852L

; read and write main memory
0852-   8E 04 C0    STX   $C004
0855-   8E 02 C0    STX   $C002

; call the quit handler (command $65)
0858-   20 00 BF    JSR   $BF00
085B-  [65 5E 08 04 00 00 00 00]

...which explains the behavior I saw on
my non-working copy.

*AC8L

; $BF30 is the last used slot and drive
; in "DSSS0000" format ("Beneath Apple
; ProDOS", p. 8-6)
0AC8-   AD 30 BF    LDA   $BF30
0ACB-   4A          LSR
0ACC-   4A          LSR
0ACD-   4A          LSR
0ACE-   4A          LSR
0ACF-   29 07       AND   #$07
0AD1-   09 C0       ORA   #$C0

; slot number munged into the high byte
; of the drive slot ROM, e.g. $C6
0AD3-   85 61       STA   $61
0AD5-   A9 00       LDA   #$00
0AD7-   85 60       STA   $60

; now look at some signature bytes in
; the peripheral ROM for the boot slot
; to determine what kind of floppy
; disk we booted from (5.25" or 3.5")
0AD9-   A0 01       LDY   #$01
0ADB-   B1 60       LDA   ($60),Y
0ADD-   C9 20       CMP   #$20
0ADF-   D0 22       BNE   $0B03
0AE1-   A0 03       LDY   #$03
0AE3-   B1 60       LDA   ($60),Y
0AE5-   D0 1C       BNE   $0B03
0AE7-   A0 05       LDY   #$05
0AE9-   B1 60       LDA   ($60),Y
0AEB-   C9 03       CMP   #$03
0AED-   D0 14       BNE   $0B03
0AEF-   A0 FF       LDY   #$FF
0AF1-   B1 60       LDA   ($60),Y
0AF3-   D0 0E       BNE   $0B03

; if 5.25-inch, use block $110 (which
; is somewhere on track $22)
0AF5-   A9 10       LDA   #$10
0AF7-   8D CE 0D    STA   $0DCE
0AFA-   A9 01       LDA   #$01
0AFC-   8D CF 0D    STA   $0DCF
0AFF-   D0 0C       BNE   $0B0D
0B01-   F0 0A       BEQ   $0B0D

; if 3.5-inch, use block $308 (this is
; the block I couldn't read when I
; tried to copy the disk)
0B03-   A9 08       LDA   #$08
0B05-   8D CE 0D    STA   $0DCE
0B08-   A9 03       LDA   #$03
0B0A-   8D CF 0D    STA   $0DCF

; fill out the rest of an MLI parameter
; table
0B0D-   AD 30 BF    LDA   $BF30
0B10-   8D CB 0D    STA   $0DCB
0B13-   A9 03       LDA   #$03
0B15-   8D CA 0D    STA   $0DCA
0B18-   A9 CA       LDA   #$CA
0B1A-   8D CC 0D    STA   $0DCC
0B1D-   A9 0B       LDA   #$0B
0B1F-   8D CD 0D    STA   $0DCD

; call MLI to read the specified block
; from disk (the $80 byte following the
; JSR is the READ_BLOCK command, and
; following that is the address of the
; MLI parameter table, $0DCA)
0B22-   20 00 BF    JSR   $BF00
0B25-  [80 CA 0D]

; if there was NOT a disk read error,
; then branch
0B28-   90 09       BCC   $0B33

; if there was any error other than an
; I/O error ($27), then branch
0B2A-   C9 27       CMP   #$27
0B2C-   D0 05       BNE   $0B33

; success path falls through to here --
; set a flag in zero page
0B2E-   A9 FF       LDA   #$FF
0B30-   85 FF       STA   $FF
0B32-   60          RTS

; failure path is here
0B33-   A9 00       LDA   #$00
0B35-   85 FF       STA   $FF
0B37-   60          RTS

This is definitely a form of copy
protection. It relies on a specific
sector being unreadable, and fails if
it's actually readable. Fun fact(*): it
is written so it can be re-used for
5.25-inch and 3.5-inch floppies. Since
my copy didn't reproduce the badness of
block $308, the MLI read routine
unexpectedly succeeds, and the program
knows it's been copied.

(*) not guaranteed, actual fun may vary

To bypass the protection, I can change
the failure path at $0B33 so it sets
the magic zero page flag to $FF instead
of $00 (just like the success path).

Block Warden
  ["C"hange device -> S5,D1]
  ["E"dit mode]
  [<Ctrl-S>earch]
    ["$20 00 BF 80"]

That will find the READ_BLOCK MLI call,
which is very close to the failure path
that I want to change.

Block $002C,offset $136 change 00 to FF

Continuing the search, Block Warden
finds another match later. (I believe
this is in the spelling list editor.)
The code is substantially similar to
what I saw in SPELL.SYSTEM.

Block $02E7,offset $133 change 00 to FF

]PR#5
...works...

Quod erat liberandum.

---------------------------------------
A 4am crack                     No. 484
------------------EOF------------------
